package org.jsola.hr.provider.impl;

import org.jsola.admin.vo.HeaderFieldsListVO;
import org.jsola.core.Page;
import org.jsola.hr.constant.HrConstants;
import org.jsola.hr.provider.ISalaryProviderService;
import org.jsola.hr.vo.JfStatisticsAnalyseVO;
import org.jsola.salary.dto.*;
import org.jsola.salary.entity.*;
import org.jsola.salary.query.ChannelFeeSettlementQuery;
import org.jsola.salary.service.*;
import org.jsola.salary.vo.*;
import org.jsola.salary.vo.excel.ChannelFeeSettlementExportVO;
import org.jsola.user.core.TokenUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhenghua
 */
@Service("hrSalaryProviderServiceImpl")
public class SalaryProviderServiceImpl implements ISalaryProviderService {

    @Autowired
    private IEmpFixedSalaryService empFixedSalaryService;

    @Autowired
    private IFixedSalaryRecordService fixedSalaryRecordService;

    @Autowired
    private IEmployeeSalaryService employeeSalaryService;

    @Autowired
    private IEmployeeSalaryNewService employeeSalaryNewService;

    @Autowired
    private ISalaryTemplateItemService salaryTemplateItemService;

    @Autowired
    private IMonthlySalaryService monthlySalaryService;

    @Autowired
    private ISalaryTemplateSalaryService salaryTemplateSalaryService;

    @Autowired
    private ISalaryTemplateService salaryTemplateService;

    @Autowired
    private IChannelFeeSettlementDetailService channelFeeSettlementDetailService;

    @Autowired
    private IEmpTaxGrandTotalService empTaxGrandTotalService;

    @Autowired
    private ISpecialAdditionalDetailService specialAdditionalDetailService;

    @Autowired
    private ICustomerDetailsService customerDetailsService;

    @Autowired
    private ICustomerDetailsNewService customerDetailsNewService;

    @Autowired
    private IEmployeeDetailsService employeeDetailsService;

    @Autowired
    private IEmployeeDetailsNewService employeeDetailsNewService;

    @Autowired
    private IDetailsAmountService detailsAmountService;

    @Autowired
    private ICustomerSettlementService customerSettlementService;

    @Autowired
    private IChannelFeeSettlementService channelFeeSettlementService;

    @Autowired
    @Lazy
    private ISalaryGroupService salaryGroupService;

    @Autowired
    @Lazy
    private ISalaryGroupSalaryService salaryGroupSalaryService;

    @Autowired
    private IEmployeeAmountService employeeAmountService;

    @Autowired
    private ISalaryTemplateHeaderService salaryTemplateHeaderService;

    @Autowired
    private IServiceChargeService serviceChargeService;

    @Autowired
    private ICustomerDetailsNewServiceChargeService customerDetailsNewServiceChargeService;

    @Override
    public List<ChannelFeeSettlementDO> feeSumByYearAndMonth(ChannelFeeSettlementQuery channelFeeSettlementQuery, TokenUser tokenUser) {
        return channelFeeSettlementService.listAllByYearAndMonth(channelFeeSettlementQuery, tokenUser);
    }

    @Override
    public List<ChannelFeeSettlementExportVO> selectExportList(ChannelFeeSettlementQuery channelFeeSettlementQuery, TokenUser tokenUser) {
        return channelFeeSettlementService.selectExportList(channelFeeSettlementQuery, tokenUser);
    }

    @Override
    public List<ChannelFeeSettlementVO> getChannelFeeSettlement(ChannelFeeSettlementQuery channelFeeSettlementQuery, TokenUser tokenUser) {
        return channelFeeSettlementService.getChannelFeeSettlement(channelFeeSettlementQuery, tokenUser);
    }

    @Override
    public List<String> updateAttendancePay(Long salaryTemplateSalaryId, String companyId, Integer yearly, Integer monthly, List<AttendancePayImportVO> list, TokenUser tokenUser) {
        return employeeSalaryService.updateAttendancePay(salaryTemplateSalaryId, companyId, yearly, monthly, list, tokenUser);
    }

    @Override
    public List<String> updateAttendancePay(Long salaryTemplateSalaryId, List<AttendancePayImportVO> list, TokenUser tokenUser) {
        return employeeAmountService.updateAttendancePay(salaryTemplateSalaryId, list, tokenUser);
    }

    @Override
    public List<EmpFixedSalaryDO> selectFixedSalaryByEmpIds(List<String> empIds) {
        return empFixedSalaryService.selectByEmpIds(empIds);
    }

    @Override
    public float getWorkTime(String empId, Integer yearly, Integer monthly, TokenUser tokenUser) {
        return employeeSalaryService.getWorkTime(empId, yearly, monthly, tokenUser);
    }

    @Override
    public float getLastMonthWorkTime(String empId, Integer yearly, Integer monthly, TokenUser tokenUser) {
        return employeeSalaryService.getLastMonthWorkTime(empId, yearly, monthly, tokenUser);
    }

    @Override
    public List<WorkTimeVO> getWorkTime(List<String> empIdList, Integer yearly, Integer monthly, TokenUser tokenUser) {
        return employeeSalaryService.getLastMonthWorkTime(empIdList, yearly, monthly, tokenUser);
    }

    @Override
    public List<WorkTimeVO> getLastMonthWorkTime(List<String> empIdList, Integer yearly, Integer monthly, TokenUser tokenUser) {
        return employeeSalaryService.getLastMonthWorkTime(empIdList, yearly, monthly, tokenUser);
    }

    @Override
    public List<EmployeeSalaryDO> selectByMonthSalaryId(Long monthSalaryId) {
        return employeeSalaryService.selectByMonthSalaryId(monthSalaryId);
    }

    @Override
    public List<EmployeeSalaryDO> selectByMonthSalaryIds(List<Long> monthSalaryIdList) {
        List<EmployeeSalaryDO> employeeSalaryDOList = new ArrayList<>();
        for (Long monthSalaryId : monthSalaryIdList) {
            List<EmployeeSalaryDO> employeeSalaryDOS = employeeSalaryService.selectByMonthSalaryId(monthSalaryId);
            if (!CollectionUtils.isEmpty(employeeSalaryDOS)) {
                employeeSalaryDOList.addAll(employeeSalaryDOS);
            }
        }
        return employeeSalaryDOList.stream()
                .sorted(Comparator.comparing(EmployeeSalaryDO::getCompanyId))
                .collect(Collectors.toList());
    }

    @Override
    public List<SalaryTemplateItemVO> selectAllUsedVoByMonthSalaryId(Long monthSalaryId, TokenUser tokenUser) {
        return salaryTemplateItemService.selectAllUsedVoByMonthSalaryId(monthSalaryId, tokenUser);
    }

    @Override
    public List<SalaryTemplateItemVO> selectAllUsedVoByMonthSalaryIds(List<Long> monthSalaryIdList, TokenUser tokenUser) {
        List<SalaryTemplateItemVO> salaryTemplateItemVOList = new ArrayList<>();
        for (Long monthSalaryId : monthSalaryIdList) {
            List<SalaryTemplateItemVO> salaryTemplateItemVOS = salaryTemplateItemService.selectAllUsedVoByMonthSalaryId(
                    monthSalaryId, tokenUser);
            if (!CollectionUtils.isEmpty(salaryTemplateItemVOS)) {
                salaryTemplateItemVOList.addAll(salaryTemplateItemVOS);
            }
        }
        return salaryTemplateItemVOList;
    }

    @Override
    public List<MonthlySalarySummaryVO> selectMonthlySalarySummaryByCompanyIds(List<String> companyIds
            , Integer yearly, Integer monthly, TokenUser tokenUser) {
        return monthlySalaryService.selectMonthlySalarySummaryByCompanyIds(companyIds, yearly, monthly, tokenUser);
    }

    @Override
    public List<MonthlySalarySummaryNewVO> selectMonthlySalarySummaryByCompanyIdsNew(List<String> companyIds
            , Integer yearly, Integer monthly, TokenUser tokenUser) {
        return monthlySalaryService.selectMonthlySalarySummaryByCompanyIdsNew(companyIds, yearly, monthly, tokenUser);
    }

    @Override
    public List<EmployeeSalaryDO> selectByCompanyIdsAndMonthly(List<String> companyIds, Integer yearly, Integer monthly, TokenUser tokenUser) {
        return employeeSalaryService.selectByCompanyIdsAndMonthly(companyIds, yearly, monthly, tokenUser);
    }


    @Override
    public List<EmployeeSalaryNewDO> selectNewByCompanyIdsAndMonthly(List<String> companyIds, Integer yearly, Integer monthly, TokenUser tokenUser) {
        return employeeSalaryNewService.selectByCompanyIdsAndMonthly(companyIds, yearly, monthly, tokenUser);
    }

    @Override
    public List<EmployeeAmountDO> selectAmountByCompanyIdsAndMonthly(List<String> companyIds, Integer yearly, Integer monthly, TokenUser tokenUser) {
        return employeeAmountService.selectByCompanyIdsAndMonthly(companyIds, yearly, monthly, tokenUser);
    }

    @Override
    public List<SalaryTemplateSalaryDO> selectTemplateByCompanyIds(Integer yearly, Integer monthly
            , List<String> companyIds, TokenUser tokenUser) {
        return salaryTemplateSalaryService.selectByMonthlyAndCompanyIds(yearly, monthly, companyIds, tokenUser);
    }

    @Override
    public List<SalaryTemplateItemVO> selectAllUsedVoBySalaryTemplateSalaryIds(List<Long> salaryTemplateSalaryIds, TokenUser tokenUser) {
        return salaryTemplateItemService.selectAllUsedVoBySalaryTemplateSalaryIds(salaryTemplateSalaryIds, tokenUser);
    }

    @Override
    public SalaryGroupSalaryVO getSalaryGroupSalaryVO(List<EmployeeSalaryDO> employeeSalaryDOList) {

        return employeeSalaryService.getSalaryGroupSalaryVO(employeeSalaryDOList);
    }

    @Override
    public List<SalaryTemplateVO> saveIssuedSeal(IssuedSalaryTemplateAddDTO issuedSalaryTemplateAddDTO, TokenUser tokenUser) {
        return salaryTemplateService.saveIssuedSeal(issuedSalaryTemplateAddDTO, tokenUser);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteFixedInfoByEmpId(String empId, TokenUser tokenUser) {
        return deleteFixedInfoByEmpIds(Collections.singletonList(empId), tokenUser);
    }

    @Override
    @Transactional(value = HrConstants.TX, rollbackFor = Exception.class)
    public int deleteFixedInfoByEmpIds(List<String> empIds, TokenUser tokenUser) {

        int i = empFixedSalaryService.deleteByEmpIds(empIds, tokenUser);
        int i1 = fixedSalaryRecordService.deleteByEmpIds(empIds, tokenUser);

        return i1;
    }

    @Override
    public List<ChannelFeeSettlementDetailDO> selectByEmpIdAndDate(String empId, String companyId, TokenUser tokenUser) {
        Calendar calendar = Calendar.getInstance();
        int yearly = calendar.get(Calendar.YEAR);
        int monthly = calendar.get(Calendar.MONTH) + 1;

        return channelFeeSettlementDetailService.selectByEmpIdAndDate(empId, companyId, yearly, monthly, tokenUser);
    }

    @Override
    public List<SpecialAdditionalDetailDO> selectSpecialAdditionalDetailByEmpId(String empId, TokenUser tokenUser) {
        return specialAdditionalDetailService.selectDoByEmpId(empId, tokenUser);
    }

    @Override
    public List<EmpTaxGrandTotalDO> selectEmpTaxGrandTotalByEmpId(String empId, String companyId, TokenUser tokenUser) {
        return empTaxGrandTotalService.selectAllByEmpId(empId, companyId, tokenUser);
    }

    @Override
    public void saveSpecialAdditionalDetail(SpecialAdditionalDetailDO specialAdditionalDetailDO) {
        specialAdditionalDetailService.onlySave(specialAdditionalDetailDO);
    }

    @Override
    public int deleteSpecialAdditionalDetailByIds(TokenUser tokenUser, Long...specialAdditionalDetailIds) {
        return specialAdditionalDetailService.deleteByIds(tokenUser, specialAdditionalDetailIds);
    }

    @Override
    public void saveEmpTaxGrandTotal(EmpTaxGrandTotalDO empTaxGrandTotalDO) {
        empTaxGrandTotalService.onlySave(empTaxGrandTotalDO);
    }

    @Override
    public int deleteEmpTaxGrandTotalByIds(TokenUser tokenUser, Long... empTaxGrandTotalIds) {
        return empTaxGrandTotalService.deleteByIds(tokenUser, empTaxGrandTotalIds);
    }

    @Override
    public CustomerDetailsDO saveCustomerDetails(CustomerDetailsAddDTO customerDetailsAddDTO, TokenUser tokenUser) {
        return customerDetailsService.save(customerDetailsAddDTO, tokenUser);
    }

    @Override
    public CustomerDetailsNewDO saveNewCustomerDetails(CustomerDetailsNewAddDTO customerDetailsNewAddDTO, TokenUser tokenUser) {
        return customerDetailsNewService.save(customerDetailsNewAddDTO, tokenUser);
    }

    @Override
    public int updateCustomerDetails(CustomerDetailsUpdateDTO customerDetailsUpdateDTO, TokenUser tokenUser) {
        return customerDetailsService.update(customerDetailsUpdateDTO, tokenUser);
    }

    @Override
    public int updateNewCustomerDetails(CustomerDetailsNewUpdateDTO customerDetailsNewUpdateDTO, TokenUser tokenUser) {
        return customerDetailsNewService.update(customerDetailsNewUpdateDTO, tokenUser);
    }

    @Override
    public List<EmployeeDetailsDO> batchSaveEmployeeDetails(List<EmployeeDetailsAddDTO> employeeDetailsAddDTOList, TokenUser tokenUser) {
        return employeeDetailsService.batchSave(employeeDetailsAddDTOList, tokenUser);
    }

    @Override
    public List<EmployeeDetailsNewDO> batchSaveNewEmployeeDetails(List<EmployeeDetailsNewAddDTO> employeeDetailsNewAddDTOList, TokenUser tokenUser) {
        return employeeDetailsNewService.batchSave(employeeDetailsNewAddDTOList, tokenUser);
    }

    @Override
    public List<DetailsAmountDO> batchSaveNewDetailsAmount(List<DetailsAmountAddDTO> detailsAmountAddDTOList, TokenUser tokenUser) {
        return detailsAmountService.batchSave(detailsAmountAddDTOList, tokenUser);
    }

    @Override
    public List<CustomerDetailsDO> selectCustomerDetailsByMonthlyAndCompanyId(Integer yearly, Integer monthly, String companyId, TokenUser tokenUser) {
        return customerDetailsService.selectByMonthlyAndCompanyId(yearly, monthly, companyId, tokenUser);
    }

    @Override
    public List<CustomerDetailsDO> selectCustomerDetailsByMonthlyCompanyIdAndType(
            Integer yearly, Integer monthly, String companyId, String type, TokenUser tokenUser) {
        return customerDetailsService.selectByMonthlyCompanyIdAndType(yearly, monthly, companyId, type, tokenUser);
    }

    @Override
    public List<CustomerDetailsNewDO> selectNewCustomerDetailsByMonthlyCompanyIdAndType(
            Integer yearly, Integer monthly, String type, List<String> companyIds, TokenUser tokenUser) {
        return customerDetailsNewService.selectByTypeAndCompanyIds(yearly, monthly, type, companyIds, tokenUser);
    }

    @Override
    public List<CustomerDetailsDO> selectCustomerDetailsByTypeAndCompanyIds(
            Integer yearly, Integer monthly, String type, List<String> companyIds, TokenUser tokenUser) {
        return customerDetailsService.selectByTypeAndCompanyIds(yearly, monthly, type, companyIds, tokenUser);
    }

    @Override
    public List<CustomerDetailsVO> selectCustomerDetailsVoByTypeAndCompanyIds(Integer yearly, Integer monthly
            , String type, List<String> companyIds, TokenUser tokenUser) {
        return customerDetailsService.selectVoByTypeAndCompanyIds(yearly, monthly, type, companyIds, tokenUser);
    }

    @Override
    public List<CustomerDetailsNewVO> selectVoAndAmountByTypeAndCompanyIds(Integer yearly, Integer monthly
            , String type, List<String> companyIds, TokenUser tokenUser) {
        return customerDetailsNewService.selectVoAndAmountByTypeAndCompanyIds(yearly, monthly, type, companyIds, tokenUser);
    }

    @Override
    public Page<CustomerDetailsNewVO> selectPageAndAmountByTypeAndCompanyIds(Integer yearly, Integer monthly
            , String type, List<String> companyIds, Integer pageNo, Integer pageSize, TokenUser tokenUser) {
        return customerDetailsNewService.selectPageAndAmountByTypeAndCompanyIds(yearly, monthly, type
                , companyIds, pageNo, pageSize, tokenUser);
    }

    @Override
    public List<EmployeeDetailsDO> selectEmployeeDetailsByCustomerDetailsIdList(List<Long> customerDetailsIdList, TokenUser tokenUser) {
        return employeeDetailsService.selectByCustomerDetailsIdList(customerDetailsIdList, tokenUser);
    }

    @Override
    public List<EmployeeDetailsNewDO> selectNewEmployeeDetailsByCustomerDetailsIdList(List<Long> customerDetailsIdList, TokenUser tokenUser) {
        return employeeDetailsNewService.selectByCustomerDetailsIdList(customerDetailsIdList, tokenUser);
    }

    @Override
    public CustomerDetailsDO selectCustomerDetailsById(Long customerDetailsId, TokenUser tokenUser) {
        return customerDetailsService.selectById(customerDetailsId, tokenUser);
    }

    @Override
    public CustomerDetailsNewDO selectCustomerDetailsNewById(Long customerDetailsNewId, TokenUser tokenUser) {
        return customerDetailsNewService.selectById(customerDetailsNewId, tokenUser);
    }

    @Override
    public List<CustomerDetailsDO> selectCustomerDetailsByIds(List<Long> customerDetailsIdList, TokenUser tokenUser) {
        return customerDetailsService.selectByIds(customerDetailsIdList, tokenUser);
    }

    @Override
    public List<CustomerDetailsNewDO> selectCustomerDetailsNewByIds(List<Long> customerDetailsNewIdList, TokenUser tokenUser) {
        return customerDetailsNewService.selectByIds(customerDetailsNewIdList, tokenUser);
    }

    @Override
    public int deleteCustomerDetailsByIds(TokenUser tokenUser, Long... customerDetailsIds) {
        return customerDetailsService.deleteByIds(tokenUser, customerDetailsIds);
    }

    @Override
    public int deleteNewCustomerDetailsByIds(TokenUser tokenUser, Long... customerDetailsIds) {
        return customerDetailsNewService.deleteByIds(tokenUser, customerDetailsIds);
    }

    @Override
    public int deleteEmployeeDetailsByIds(TokenUser tokenUser, Long... employeeDetailsIds) {
        return employeeDetailsService.deleteByIds(tokenUser, employeeDetailsIds);
    }

    @Override
    public int deleteNewEmployeeDetailsByIds(TokenUser tokenUser, Long... employeeDetailsIds) {
        return employeeDetailsNewService.deleteByIds(tokenUser, employeeDetailsIds);
    }

    @Override
    public CustomerDetailsDO selectCustomerDetailsLastOne(List<String> companyIds, TokenUser tokenUser) {
        return customerDetailsService.selectLastOne(companyIds, tokenUser);
    }

    @Override
    public CustomerDetailsNewDO selectNewCustomerDetailsLastOne(List<String> companyIds, TokenUser tokenUser) {
        return customerDetailsNewService.selectLastOne(companyIds, tokenUser);
    }

    @Override
    public List<CustomerSettlementDO> batchSaveCustomerSettlement(
            List<CustomerSettlementAddDTO> customerSettlementAddDTOList, TokenUser tokenUser) {
        return customerSettlementService.batchSave(customerSettlementAddDTOList, tokenUser);
    }

    @Override
    public int deleteEmployeeSalaryNotArchiveByEmpIds(List<String> empIds, TokenUser tokenUser) {
        return employeeSalaryService.deleteNotArchiveByEmpIds(empIds, tokenUser);
    }

    @Override
    public List<SalaryGroupVO> selectSalaryGroupByCompanyId(String companyId) {
        return salaryGroupService.selectByCompanyId(companyId);
    }

    @Override
    public List<SalaryGroupDO> selectSalaryGroupByCompanyIds(List<String> companyIds) {
        return salaryGroupService.selectByCompanyIds(companyIds);
    }

    @Override
    public List<SalaryGroupSalaryDO> selectCreatedSalaryGroupSalary(Integer yearly, Integer monthly, String companyId) {
        return salaryGroupSalaryService.selectCreatedSalaryGroup(yearly, monthly, companyId);
    }

    @Override
    public List<SalaryGroupSalaryDO> selectCreatedSalaryGroupByCompanyIds(Integer yearly, Integer monthly, List<String> companyIds) {
        return salaryGroupSalaryService.selectCreatedSalaryGroupByCompanyIds(yearly, monthly, companyIds);
    }

    @Override
    public List<HeaderFieldsListVO> selectAllHeaderDetailNew(String companyId, String moduleCode, Long sourceId, TokenUser tokenUser) {
        return salaryTemplateHeaderService.selectAllHeaderDetailNew(companyId, moduleCode, sourceId, tokenUser);
    }

    @Override
    public List<DetailsAmountDO> selectDetailsAmountByTypeAndIds(String sourceType, List<Long> sourceIds, TokenUser tokenUser) {
        return detailsAmountService.selectByTypeAndIds(sourceType, sourceIds, tokenUser);
    }

    @Override
    public List<EmployeeAmountDO> selectAmountByEmpSalaryNewIds(List<Long> employeeSalaryNewIds, TokenUser tokenUser) {
        return employeeAmountService.selectAmountByEmpSalaryNewIds(employeeSalaryNewIds, tokenUser);
    }

    @Override
    public JfStatisticsAnalyseListVO jfStatisticsAnalyseLaborCosts(String companyId, Integer yearly, TokenUser tokenUser) {
        return customerDetailsNewService.jfStatisticsAnalyseLaborCosts(companyId, yearly, tokenUser);
    }

    @Override
    public List<ServiceChargeDO> selectServiceChargeByIds(List<Long> serviceChargeIdList, TokenUser tokenUser) {
        return serviceChargeService.selectByIds(serviceChargeIdList, tokenUser);
    }

    @Override
    public List<CustomerDetailsNewServiceChargeDO> batchSaveCustomerDetailsNewServiceCharge(
            List<CustomerDetailsNewServiceChargeAddDTO> customerDetailsNewServiceChargeAddDTOList, TokenUser tokenUser) {
        return customerDetailsNewServiceChargeService.batchSave(customerDetailsNewServiceChargeAddDTOList,tokenUser);
    }

    @Override
    public List<CustomerDetailsNewServiceChargeDO> selectCustomerDetailsNewServiceChargeByCustomerDetailsNewIds(
            List<Long> customerDetailsNewIds, TokenUser tokenUser) {
        return customerDetailsNewServiceChargeService.selectByCustomerDetailsNewIds(customerDetailsNewIds, tokenUser);
    }

}
